<?php
namespace app\common\service;


class WeChatService
{
    protected static $appId='wxfc5a58db32637103';      //微信appId

    protected static $appSecret='1b6d65bc58a0c01e2466f7944f5a2ac2';

    public $encodingAesKey; //微信加密encodingAesKey

    /*function __construct($appId,$appSecret){
        $this->appId = $appId;
        $this->appSecret = $appSecret;
    }*/








    /*获取用户openid 与 网页授权access_token
    $scope snsapi_base(不弹出授权页面，直接跳转，只能获取用户openid)，snsapi_userinfo(弹出授权页面，可通过openid拿到昵称、性别、所在地。)。默认为snsapi_base。
    */
    public static function getOpenid($scope=''){
        $redirect_uri 	= "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
        $codeUrl 		= self::get_code_url($redirect_uri,$scope);
        if(empty($_GET['code']) && empty($_GET['state'])){
            header("Location: $codeUrl");
            exit;
        }else{
            $code 	= $_GET['code'];
            if(!empty($code)){
                $res = self::get_web_access_token($code);
                if(empty($res['errcode'])){
                    $data 	= array(
                        'access_token'	=> $res['access_token'],
                        'openid'		=> $res['openid'],
                    );
                    return $data;
                }else{
                    header("Location: $redirect_uri");
                    exit('授权错误，请检查公众号权限和设置');
                }
            }
        }
    }


    /*组装code的url*/
    public static function get_code_url($redirect_uri ='',$scope='snsapi_base', $state = 'oauth'){
        $redirect_uri = urlencode($redirect_uri);
        $url 	=  "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".self::$appId."&redirect_uri=".$redirect_uri."&response_type=code&scope=".$scope."&state=".$state;
        $url .= '#wechat_redirect';
        return $url;

    }
    /*获取网页授权access_token
    $code  微信返回的code
    */
    public static function get_web_access_token($code){
        $tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".self::$appId."&secret=".self::$appSecret."&code=".$code."&grant_type=authorization_code";
        $res 	= self::https_request($tokenUrl);
        return $res;

    }
    /*发送请求*/
    public static function https_request($url, $data = null){
        $curl = curl_init();
        $header = array("Accept-Charset: utf-8");
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        //curl_setopt($curl, CURLOPT_SSLVERSION, 3);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        $errorno= curl_errno($curl);
        if ($errorno) {
            return array('curl'=>false,'errorno'=>$errorno);
        }else{
            $res = json_decode($output,1);
            if (isset($res['errcode']) && $res['errcode']){
                return array('errcode'=>$res['errcode'],'errmsg'=>$res['errmsg']);
            }else{
                return $res;
            }
        }
        curl_close($curl);
    }


    private static function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }


    public static function getSignPackage() {

        $jsapiTicket = self::getJsApiTicket();

        // 注意 URL 一定要动态获取，不能 hardcode.
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
        if($_SERVER["HTTP_REFERER"]){
            $url = $_SERVER["HTTP_REFERER"];
        }

        $timestamp = time();
        $nonceStr = self::createNonceStr();

        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

        $signature = sha1($string);

        $signPackage = array(
            "appId"     => self::$appId,
            "nonceStr"  => $nonceStr,
            "timestamp" => $timestamp,
            "url"       => $url,
            "signature" => $signature,
            "rawString" => $string
        );
        return $signPackage;
    }

    private static function getJsApiTicket() {
        // jsapi_ticket 应该全局存储与更新，以下代码以写入到文件中做示例
        $data = json_decode(self::get_php_file("jsapi_ticket.php"));
        if ($data->expire_time < time()) {
            $accessToken = self::getAccessToken();
            // 如果是企业号用以下 URL 获取 ticket
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
            $res = json_decode(self::httpGet($url));
            $ticket = $res->ticket;
            if ($ticket) {
                $data->expire_time = time() + 7000;
                $data->jsapi_ticket = $ticket;
                self::set_php_file("jsapi_ticket.php", json_encode($data));
            }
        } else {
            $ticket = $data->jsapi_ticket;
        }

        return $ticket;
    }


    private static function getAccessToken() {
        // access_token 应该全局存储与更新，以下代码以写入到文件中做示例
        $data = json_decode(self::get_php_file("access_token.php"));
        if ($data->expire_time < time()) {
            // 如果是企业号用以下URL获取access_token
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
//            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=self::$appid&secret=$this->appSecret";

            $url = sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",self::$appId,self::$appSecret);

            $res = json_decode(self::httpGet($url));
            $access_token = $res->access_token;
            if ($access_token) {
                $data->expire_time = time() + 7000;
                $data->access_token = $access_token;
                self::set_php_file("access_token.php", json_encode($data));
            }
        } else {
            $access_token = $data->access_token;
        }
        return $access_token;
    }

    private static function httpGet($url) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        // 为保证第三方服务器与微信服务器之间数据传输的安全性，所有微信接口采用https方式调用，必须使用下面2行代码打开ssl安全校验。
        // 如果在部署过程中代码在此处验证失败，请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
        curl_setopt($curl, CURLOPT_URL, $url);

        $res = curl_exec($curl);
        curl_close($curl);

        return $res;
    }

    private static function get_php_file($filename) {
        return trim(substr(file_get_contents($filename), 15));
    }

    private static function set_php_file($filename, $content) {
        $fp = fopen($filename, "w");
        fwrite($fp, "<?php exit();?>" . $content);
        fclose($fp);
    }


}
?>